home *** CD-ROM | disk | FTP | other *** search
- { scan.pas -- Scan hard drive and report file statistics }
-
- {$M 16384, 8192}
-
- program Scan;
-
- {$R scan.res}
-
- uses WinDOS, WinTypes, WinProcs, WObjects, Strings, StdDlgs, Status;
-
- const
-
- id_Menu = 100; { Menu resource ID }
- cm_Scan = 101; { Command IDs }
- cm_Exit = 102;
-
- type
-
- DataType = (dtNumFiles, dtNumDirectories, dtMaxLevel,
- dtSmallestFile, dtLargestFile, dtAvgFileSize,
- dtDiskSize, dtFileBytes, dtBytesFree);
-
- const
-
- FirstDataType = dtNumFiles;
- LastDataType = dtBytesFree;
- LabelArray: array[DataType] of PChar = (
- 'Number of nonnull files: ',
- 'Number of directories: ',
- 'Maximum directory level: ',
- 'Smallest file in bytes: ',
- 'Largest file in bytes: ',
- 'Average file size in bytes: ',
- 'Disk size in bytes: ',
- 'Bytes used by files: ',
- 'Total bytes free: '
- );
-
- type
-
- ScanApplication = object(TApplication)
- procedure InitMainWindow; virtual;
- end;
-
- PScanWindow = ^ScanWindow;
- ScanWindow = object(TWindow)
- Drive: Char; { Drive letter }
- Scanning: Boolean; { True while scan is in progress }
- DataArray: array[DataType] of LongInt;
- LargestPath, SmallestPath: array[0 .. fsPathName] of Char;
- StatusDialog: PStatus;
- constructor Init(AParent: PWindowsObject; ATitle: PChar);
- function CanClose: Boolean; virtual;
- procedure ZeroFields;
- function ScanDrive(D: Char): Boolean;
- procedure CMScan(Msg: TMessage);
- virtual cm_First + cm_Scan;
- procedure CMQuit(Msg: TMessage);
- virtual cm_First + cm_Exit;
- procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
- virtual;
- end;
-
-
- { ScanApplication }
-
- {- Initialize ScanApplication object's window }
- procedure ScanApplication.InitMainWindow;
- begin
- MainWindow := New(PScanWindow, Init(nil, ''))
- end;
-
-
- { ScanWindow }
-
- {- Construct ScanWindow object }
- constructor ScanWindow.Init(AParent: PWindowsObject; ATitle: PChar);
- begin
- TWindow.Init(AParent, ATitle);
- with Attr do
- begin
- Menu := LoadMenu(HInstance, PChar(id_Menu));
- X := 10; Y := 10; W := 350; H := 400
- end;
- StatusDialog := nil;
- Scanning := false;
- ZeroFields
- end;
-
- {- Return true if main window may be closed }
- function ScanWindow.CanClose: Boolean;
- begin
- CanClose := not Scanning
- end;
-
- {- Set data fields to zero }
- procedure ScanWindow.ZeroFields;
- begin
- Drive := #0;
- FillChar(DataArray, Sizeof(DataArray), 0);
- LargestPath[0] := #0;
- SmallestPath[0] := #0
- end;
-
- {- Scan drive and update statistics. Return true for success }
- { Requires initialized StatusDialog object pointer }
- function ScanWindow.ScanDrive(D: Char): Boolean;
- var
- P: PChar;
-
- {- Read file and path names recursively }
- procedure ReadDirectory(Level: Integer);
- var
- Sr: TSearchRec; { Directory search record }
- LocalDir: array[0 .. fsDirectory] of Char; { Current path }
- LocalName: array[0 .. fsPathName] of Char; { Current dir + file }
- IsFileEntry: Boolean; { True except for '.' and '..' }
- begin
- Inc(DataArray[dtNumDirectories]);
- if Level > DataArray[dtMaxLevel] then
- DataArray[dtMaxLevel] := Level;
- LocalDir[0] := #0;
- GetCurDir(LocalDir, 0);
- StatusDialog^.Update1(LocalDir);
- FindFirst('*.*', faAnyFile, Sr);
- while (DosError = 0) and (StatusDialog^.Continue) do with Sr do
- begin
- IsFileEntry := Name[0] <> '.';
- if IsFileEntry and (Attr and faDirectory <> 0) then
- begin
- SetCurDir(Name); { Change to next level }
- ReadDirectory(Level + 1); { Process files there }
- SetCurDir('..') { Return to previous level }
- end else if IsFileEntry and (Size > 0) then
- begin
- StatusDialog^.Update2(Name);
- StrCopy(LocalName, LocalDir);
- if LocalName[StrLen(LocalName) - 1] <> '\' then
- StrCat(LocalName, '\');
- StrCat(LocalName, Name);
- Inc(DataArray[dtNumFiles]);
- Inc(DataArray[dtFileBytes], Size);
- if Size < DataArray[dtSmallestFile] then
- begin
- DataArray[dtSmallestFile] := Size;
- StrCopy(SmallestPath, LocalName)
- end;
- if Size > DataArray[dtLargestFile] then
- begin
- DataArray[dtLargestFile] := Size;
- StrCopy(LargestPath, LocalName)
- end
- end;
- FindNext(Sr)
- end
- end;
-
- begin
- ZeroFields;
- P := 'X:\';
- P[0] := D; { Replace 'X' with D }
- SetCurDir(P);
- if DosError <> 0 then ScanDrive := false else
- begin
- Scanning := true; { Prevent window from closing }
- StatusDialog^.BeginStatus('Scanning files...');
- DataArray[dtSmallestFile] := maxLongInt;
- DataArray[dtDiskSize] := DiskSize(0);
- DataArray[dtBytesFree] := DiskFree(0);
- ReadDirectory(0);
- if DataArray[dtNumFiles] = 0 then
- DataArray[dtSmallestFile] := 0
- else
- DataArray[dtAvgFileSize] :=
- DataArray[dtFileBytes] div DataArray[dtNumFiles];
- ScanDrive := StatusDialog^.Continue; { i.e. not canceled }
- StatusDialog^.EndStatus;
- Scanning := false { Permit window to close }
- end
- end;
-
- {- Execute File:Scan command }
- procedure ScanWindow.CMScan(Msg: TMessage);
- var
- Buffer: array[0 .. 2] of Char;
- begin
- if Scanning then Exit; { Only one scan at a time }
- Buffer[0] := #0;
- if Application^.ExecDialog(New(PInputDialog,
- Init(@Self, 'Prompt', 'Enter letter of drive to scan: ',
- Buffer, Sizeof(Buffer)))) = id_Ok then
- if StrLen(Buffer) <> 0 then
- begin
- if StatusDialog = nil then
- begin { Create new Scan status dialog }
- StatusDialog := PStatus(
- Application^.MakeWindow(New(PStatus, Init(@Self, statusID))));
- if StatusDialog = nil then
- Application^.Error(em_OutOfMemory)
- else
- StatusDialog^.ChangeTitle('File Scan Status')
- end;
- if StatusDialog <> nil then
- begin
- if ScanDrive(Buffer[0]) then
- Drive := Upcase(Buffer[0]);
- InvalidateRect(HWindow, nil, true)
- end
- end
- end;
-
- {- Execute File:Exit command }
- procedure ScanWindow.CMQuit(Msg: TMessage);
- begin
- CloseWindow
- end;
-
- {- Paint contents of window. Displays current statistics. }
- procedure ScanWindow.Paint(PaintDC: HDC;
- var PaintInfo: TPaintStruct);
- var
- DT: DataType;
- X, Y, YDelta: Integer;
- S: String[11];
- P: PChar;
- Len: Word;
- Extent: LongInt;
-
- {- Display pathname P and advance Y by YDelta }
- procedure ShowPath(P: PChar);
- begin
- if (P <> nil) and (StrLen(P) > 0) then
- begin
- TextOut(PaintDC, X + 4, Y, P, StrLen(P));
- Inc(Y, YDelta)
- end
- end;
-
- begin
- if Drive = #0 then
- P := 'No drive selected'
- else begin
- P := 'Statistics for drive X:';
- P[21] := Drive
- end;
- SetWindowText(HWindow, P);
- Y := 10;
- for DT := FirstDataType to LastDataType do
- begin
- X := 10;
- P := LabelArray[DT];
- Len := StrLen(P);
- Extent := GetTextExtent(PaintDC, P, Len);
- TextOut(PaintDC, X, Y, P, Len);
- Str(DataArray[DT], S);
- TextOut(PaintDC, X + LOWORD(Extent), Y, @S[1], Length(S));
- YDelta := HIWORD(Extent * 2);
- Inc(Y, YDelta);
- if DT = dtSmallestFile then
- ShowPath(SmallestPath)
- else if DT = dtLargestFile then
- ShowPath(LargestPath)
- end;
- end;
-
- var
-
- ScanApp: ScanApplication;
-
- begin
- ScanApp.Init('ScanApp');
- ScanApp.Run;
- ScanApp.Done
- end.
-
-
- {--------------------------------------------------------------
- Copyright (c) 1991 by Tom Swan. All rights reserved.
- Revision 1.00 Date: 5/4/1991
- ---------------------------------------------------------------}
-